home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 March
/
EnigmA AMIGA RUN 05 (1996)(G.R. Edizioni)(IT)[!][issue 1996-03][Skylink CD IV].iso
/
earcd
/
comm2
/
alist.lha
/
src
/
alpost.e
< prev
next >
Wrap
Text File
|
1995-11-08
|
15KB
|
448 lines
/* ALPost.M */
OPT MODULE
OPT EXPORT
/* Module to post messages to lists managed by this server */
MODULE 'dos/datetime'
MODULE 'dos/dos'
MODULE 'other/aladd'
MODULE 'other/alcmd'
MODULE 'other/alconfig'
MODULE 'other/allog'
/* These are for the replace_strings() function */
SET RPLC_LIST, RPLC_OWN, RPLC_FROM, RPLC_TO, RPLC_DATE, RPLC_SUBJ, RPLC_KEY, RPLC_MSG, RPLC_OUT
/* Everything that's currently supported */
CONST RPLC_ALL=RPLC_LIST OR RPLC_OWN OR RPLC_FROM
DEF temp_file:PTR TO CHAR, hostname:PTR TO CHAR, list_dir
/*
* Directs a message to the appropriate destination.
*/
PROC examine_message (str:PTR TO CHAR)
DEF str1:PTR TO CHAR, tmp:PTR TO config_node, str2:PTR TO CHAR, flag
LowerStr (str)
IF (StrCmp (str, 'alist'))
do_command (str)
RETURN
ENDIF
flag := 0
str1 := InStr (str, '-list-request')
IF (str1 = -1)
str1 := InStr (str, '-request')
IF (str1 = -1)
str1 := InStr (str, '-list-owner')
IF (str1 = -1)
str1 := InStr (str, '-owner')
IF (str1 = -1)
str1 := InStr (str, '-list')
ELSE
flag := 2 /* -owner, forward to the owner */
ENDIF
ELSE
flag := 2 /* -list-owner, forward to the owner */
ENDIF
ELSE
flag := 1 /* -request, forward to AList, with a default list */
ENDIF
ELSE
flag := 1 /* -list-request, forward to AList, with a default list */
ENDIF
IF (str1 > -1)
str1 := String (str1)
StrCopy (str1, str)
ELSE
str1 := str
ENDIF
tmp := find_list (str1)
IF (tmp = NIL)
clear_tmp_file()
add_tmp_file ('\nNo user or mailing list by the name of "')
add_tmp_file (str1)
add_tmp_file ('" found.\n\n')
str2 := String (71 + StrLen (Next (str)))
StringF (str2, '-f AList -R "AList Mailing List Server" -s "BOUNCE: No such user" -t "\s"', Next (str))
send_message (str2)
DisposeLink (str2)
ELSE
/* Found a list it goes to */
IF (flag = 2)
/* It's a -owner message, it should go to the owner. */
clear_tmp_file ()
fill_tmp_file (Next (Next (str)))
str2 := String (5 + StrLen (tmp.owner))
StringF (str2, '-t "\s"', tmp.owner)
send_message (str2)
DisposeLink (str2)
ELSEIF (flag = 1)
/* It's a -request, it should go to the AList with a default list */
/* Note that str1 is NOT equal to str, if we got here. */
Link (str1, Next(str))
do_command (str1)
ELSE
/* It's a post */
post_list (tmp, Next (str), Next (Next (str)))
ENDIF
ENDIF
IF (str1 <> str) THEN DisposeLink (str1)
ENDPROC
/*
* Post a message to a list, passing the arguments on to SMTPpost
*/
PROC send_message (str)
DEF str2:PTR TO CHAR, tmp
IF (str)
str2 := String (StrLen (str) + EstrLen (temp_file) + 19)
StrCopy (str2, 'SMTPpost <"')
StrAdd (str2, temp_file)
StrAdd (str2, '" >NIL: ')
StrAdd (str2, str)
ELSE
str2 := String (EstrLen (temp_file) + 19)
StrCopy (str2, 'SMTPpost <"')
StrAdd (str2, temp_file)
StrAdd (str2, '" >NIL: ')
ENDIF
IF (Execute (str2, NIL, NIL))
log_message ('Mailed: ', LOG_INFO)
log_message (str2, LOG_INFO2)
log_message ('\n', LOG_INFO2)
ELSE
log_message ('SMTPpost Failed: ', LOG_ERROR)
log_message (str2, LOG_ERROR2)
log_message ('\n', LOG_ERROR2)
ENDIF
DisposeLink (str2)
ENDPROC
/*
* Post a message to the list, based on the list options
*
* msg is really a linked estring chain containing first headers then the body
*/
PROC post_list (list:PTR TO config_node, from:PTR TO CHAR, msg:PTR TO CHAR)
DEF is_header, has_subject, who:PTR TO CHAR, str:PTR TO CHAR, prev, i, flag
DEF h_from, h_subj, h_date, tmpstr, fd, stamp:PTR TO datestamp, old_dir, str2
clear_tmp_file()
h_from := h_subj := h_date := NIL
str := String (31 + (2 * EstrLen (list.name)))
StringF (str, '-f \s-list-owner -t \s-list-members', list.name, list.name)
is_header := (is_empty (msg) = FALSE); has_subject := FALSE; prev := NIL
WHILE (IF (msg) THEN (is_header) ELSE FALSE)
IF (IF (list.subject) THEN (StrCmp (msg, 'Subject: ', 9)) ELSE FALSE)
has_subject := InStr (msg, list.subject) /* This will never be 0 */
IF (has_subject = -1)
who := String (EstrLen (msg) + EstrLen (list.subject))
StringF (who, 'Subject: \s\s', list.subject, msg + 9)
/* A little hack here, since the only place that calls this uses msg as Next (from) */
IF (prev) THEN Link (prev, who) ELSE Link (from, who)
Link (who, Next (msg))
Link (msg, NIL) /* We don't want to unlink the rest of the message! */
DisposeLink (msg)
msg := who
ENDIF
ENDIF
IF (list.digest)
IF (StrCmp (msg, 'Subject: ', 9))
h_subj := msg
ELSEIF (StrCmp (msg, 'From: ', 6))
h_from := msg
ELSEIF (StrCmp (msg, 'Date: ', 6))
h_date := msg
ENDIF
ENDIF
/* Content-Length: is always wrong here */
IF (StrCmp (msg, 'Content-Length:', 15) = FALSE) AND
(StrCmp (msg, 'Approved:', 9) = FALSE)
add_tmp_file (msg)
ENDIF
prev := msg
msg := Next (msg)
is_header := (is_empty (msg) = FALSE)
ENDWHILE
IF (IF (has_subject = FALSE) THEN (list.subject <> NIL) ELSE FALSE)
/* add in subject */
who := String (10 + EstrLen (list.subject))
StringF (who, 'Subject: \s\n', list.subject)
/* See the comment above on this hack */
IF (prev) THEN Link (prev, who) ELSE Link (from, who)
Link (who, msg)
prev := who
add_tmp_file (who)
IF (list.digest) THEN h_subj := who
ENDIF
who := list.users
IF (who) THEN add_tmp_file ('Bcc: ')
i := 5
WHILE (who)
add_tmp_file (who)
IF (Next (who))
add_tmp_file (', ')
i := i + EstrLen (who) + 2
IF (i > 60)
add_tmp_file ('\n\t')
i := 8
ENDIF
ENDIF
who := Next (who)
ENDWHILE
add_tmp_file ('\n')
/* Add in the headers, if any */
IF (list.header)
who := String (EstrLen (list.header))
StrCopy (who, list.header)
who := replace_strings (RPLC_ALL, who, list, from)
add_tmp_file (who)
DisposeLink (who)
ENDIF
fd := NIL
IF (list.digest)
tmpstr := String (EstrLen (list.name) + 7)
StringF (tmpstr, '\s.digest', list.name)
old_dir := CurrentDir (list_dir)
fd := Open (tmpstr, MODE_READWRITE)
IF (fd = NIL)
log_message ('Unable to open digest file for list "', LOG_ERROR)
log_message (list.name, LOG_ERROR2)
log_message ('".\n', LOG_ERROR2)
ELSE
Seek (fd, 0, OFFSET_END)
IF (list.digest.time = NIL)
/* List hasn't been opened yet */
IF (Seek (fd, 0, OFFSET_CURRENT) > 1)
/* We aren't at the start of the file! */
log_message ('Time/Date stamp and Number of Lines lost for existing digest\n' +
'\tfor list "', LOG_ERROR)
log_message (list.name, LOG_ERROR2)
log_message ('"!\n', LOG_ERROR2)
list.digest.current_size := Seek (fd, 0, OFFSET_CURRENT)
ELSE
list.digest.current_size := NIL
ENDIF
list.digest.time := DateStamp (New (SIZEOF datetime))
list.digest.current_lines := 4 /* The Subject: xxx\n\n*** BEGIN ... *** \n lines */
who := String (80)
StringF (who, 'Subject: \s Digest, \s #\d', list.name,
IF (list.digest.iname) THEN list.digest.iname ELSE 'ISSUE', list.digest.issue)
Fputs (fd, who)
IF (list.digest.volume)
StringF (who, ' \s #\d\n', IF (list.digest.vname) THEN list.digest.vname ELSE 'VOLUME', list.digest.volume)
Fputs (fd, who)
ELSE
FputC (fd, "\n")
ENDIF
IF (list.digest.header)
Fputs (fd, list.digest.header)
list.digest.current_lines := list.digest.current_lines + count (list.digest.header, "\n")
ENDIF
StringF (who, '\n*** BEGIN DIGEST \s #\d', IF (list.digest.iname) THEN list.digest.iname ELSE 'ISSUE', list.digest.issue)
Fputs (fd, who)
IF (list.digest.volume)
StringF (who, ', \s #\d', IF (list.digest.vname) THEN list.digest.vname ELSE 'VOLUME', list.digest.volume)
ENDIF
Fputs (fd, who)
Fputs (fd, ' ***\n')
DisposeLink (who)
list.digest.current_size := Seek (fd, 0, OFFSET_CURRENT)
ELSE
/* It's a second or higher message, add in the separator */
Fputs (fd, '\n')
IF (list.digest.footer)
Fputs (fd, list.digest.footer)
list.digest.current_lines := list.digest.current_lines + count (list.digest.footer, "\n") + 1
ENDIF
ENDIF
Fputs (fd, '\n')
IF (h_from)
Fputs (fd, h_from)
ELSE
Fputs (fd, 'From: ???\n')
ENDIF
IF (h_date)
Fputs (fd, h_date)
ELSE
/* REALLY should calc date from list.digest.time here, it's already a DateTime struct... */
Fputs (fd, 'Date: ???\n')
ENDIF
IF (h_subj)
Fputs (fd, h_subj)
ELSE
Fputs (fd, 'Subject: (no subject)\n')
ENDIF
Fputs (fd, '\n')
list.digest.current_lines := list.digest.current_lines + 5
ENDIF
ENDIF
/* Now add the rest of the message */
WHILE (msg)
add_tmp_file (msg)
IF (fd)
Fputs (fd, msg)
list.digest.current_lines := list.digest.current_lines + 1
ENDIF
msg := Next (msg)
ENDWHILE
/* Now add the footer, if any */
IF (list.header) THEN add_tmp_file (list.footer)
send_message (str)
/* Check if we need to send a digest issue */
IF (fd)
list.digest.current_size := Seek (fd, 0, OFFSET_CURRENT)
flag := 0
IF (list.digest.lines)
IF (list.digest.current_lines >= list.digest.lines) THEN flag := 1
IF (flag = 1) THEN WriteF ('lines flip: current=\d, max=\d\n', list.digest.current_lines, list.digest.lines)
ENDIF
IF (list.digest.size)
IF (list.digest.current_size >= Shl (list.digest.size, 10)) THEN flag := 2
IF (flag=2) THEN WriteF ('size flip: current=\d, max=\dK\n', list.digest.current_size, list.digest.size)
ENDIF
IF (list.digest.age)
NEW stamp
stamp := DateStamp (stamp)
IF ((stamp.days - list.digest.age) >= list.digest.time.stamp.days) THEN flag := 4
IF (flag=4) THEN WriteF ('age flip: current=\d, first=\d, max=\d\n', stamp.days, list.digest.time.stamp.days, list.digest.age)
END stamp
ENDIF
IF (flag)
/* Gotta send a digest issue */
who := String (80)
StringF (who, '\n*** END DIGEST \s #\d', IF (list.digest.iname) THEN list.digest.iname ELSE 'ISSUE', list.digest.issue)
Fputs (fd, who)
list.digest.issue := list.digest.issue + 1
IF (list.digest.volume)
StringF (who, ', \s #\d ***\n', IF (list.digest.vname) THEN list.digest.vname ELSE 'VOLUME', list.digest.volume)
Fputs (fd, who)
IF (list.digest.issue > list.digest.i_v)
list.digest.issue := 1
list.digest.volume := list.digest.volume + 1
ENDIF
ELSE
Fputs (fd, ' ***\n\n')
ENDIF
list.digest.current_lines := 0
list.digest.current_size := 0
Seek (fd, 0, OFFSET_BEGINNING)
who := load_in_file (fd)
str2 := String (EstrLen (list.name) + StrLen (hostname) + 1)
StringF (str2, '\s@\s', list.name, hostname)
/* WARNING: This could cause an endless loop if digest lists have digests! */
post_list (find_list (list.digest.name), str2, who)
DisposeLink (who)
Close (fd)
DeleteFile (tmpstr)
Dispose (list.digest.time)
list.digest.time := NIL
ELSE
Close (fd)
ENDIF
write_issue (list)
CurrentDir (old_dir)
DisposeLink (tmpstr)
ENDIF
ENDPROC
/*
* Replace certain strings, based on flags
*
* $MSG Entire message (really, temp file name).
* $OUT File used to collect the output.
* $USER Don't use this one. (Only valid on crypt/decrypt anyway)
* $FROM Sender of the message.
* $TO Only used for crypt/decrypt.
* $KEY Only used for crypt/decrypt.
* $DATE Full date string.
* $SUBJ The subject line.
* $LIST List name.
* $OWN List owner.
*/
PROC replace_strings (flags, str:PTR TO CHAR, list:PTR TO config_node,
from=NIL, to=NIL, date=NIL, subj=NIL, key=NIL)
DEF str1:PTR TO CHAR
IF (str = NIL) OR (list = NIL) THEN RETURN
IF (flags AND RPLC_LIST)
IF (hostname)
str1 := String (StrLen (list.name) + StrLen (hostname) + 1)
StringF (str1, '\s@\s', list.name, hostname)
str := low_replace (str, '$LIST', str1)
DisposeLink (str1)
ELSE
str := low_replace (str, '$LIST', list.name)
ENDIF
ENDIF
IF (flags AND RPLC_OWN) THEN str := low_replace (str, '$OWN', list.owner)
IF (flags AND RPLC_FROM) THEN str := low_replace (str, '$FROM', from)
IF (flags AND RPLC_TO) THEN str := low_replace (str, '$TO', to)
IF (flags AND RPLC_DATE) THEN str := low_replace (str, '$DATE', date)
IF (flags AND RPLC_SUBJ) THEN str := low_replace (str, '$SUBJ', subj)
IF (flags AND RPLC_KEY) THEN str := low_replace (str, '$KEY', key)
IF (flags AND RPLC_MSG) THEN str := low_replace (str, '$MSG', temp_file)
IF (flags AND RPLC_OUT) THEN str := low_replace (str, '$OUT', 'T:alist.out')
ENDPROC str
/*
* low-level function for string replacement
*/
PROC low_replace (str:PTR TO CHAR, fix:PTR TO CHAR, ins:PTR TO CHAR)
DEF s:PTR TO CHAR, x, s2:PTR TO CHAR, len, len2
x := 0; s2 := str; len := StrLen (fix)
IF (ins) THEN len2 := StrLen (ins) ELSE len2 := NIL
WHILE ((x := InStr (s2, fix, x)) > -1)
s := String (EstrLen (s2) - len + len2)
IF (x > 0) THEN StrCopy (s, s2, x-1)
IF (len2) THEN StrAdd (s, ins)
IF (x+len < EstrLen (s2)) THEN StrAdd (s, s2+x+len)
DisposeLink (s2)
s2 := s
x := x + len2
ENDWHILE
ENDPROC s2